/*
 * OperationalSemanticsChooser.h
 *
 *  Created on: Oct 29, 2012
 *      Author: raul
 */

#ifndef OPERATIONALSEMANTICSCHOOSER_H_
#define OPERATIONALSEMANTICSCHOOSER_H_

#define MAX_NEW_NODES 1000

#include "SyntacticTreeLibrary.h"

typedef struct {
	int numOfStates;
	stateLTS obtainedStates[MAX_NEW_NODES];
} processingOutput;

int oS_deterministicStability(Node *tree) {
	int result = 1;

	int type = sT_getType(tree);

	if (type == IN_CHO) {
		return 0;
	}

	if (type == PREFIX || type == SEQ_PROC) {
		if (tree->left) {
			result *= oS_deterministicStability(tree->left);
		}
	}

	if (type == EXT_CHO || type == PARALLEL || type == PR_CHO) {
		if (tree->left) {
			result *= oS_deterministicStability(tree->left);
		}
		if (tree->right) {
			result *= oS_deterministicStability(tree->right);
		}
	}

	return result;
}

int oS_action(Node *tree) {
	int result = 1;

	int type = sT_getType(tree);

	if (type == PR_CHO) {
		return 0;
	}

	if (type == PREFIX || type == SEQ_PROC) {
		if (tree->left) {
			result *= oS_deterministicStability(tree->left);
		}
	}

	if (type == EXT_CHO || type == PARALLEL) {
		if (tree->left) {
			result *= oS_deterministicStability(tree->left);
		}
		if (tree->right) {
			result *= oS_deterministicStability(tree->right);
		}
	}

	return result;
}

void oS_processingNode(stateLTS *LTSnode, processingOutput *result) {

	result->numOfStates = 0;

	Node *node = LTSnode->node;

//First of all, we must know if the process is deterministically stable
	if (!oS_deterministicStability(node)) {
//		printf("This node is NOT deterministically stable\n");
		solvingInternalChoice(LTSnode, node, NULL, LTSnode->id, result);
	} else {
//		printf("This node is deterministically stable\n");

//Now let's check if the can evolvo through action rules
		if (!oS_action(node)) {
//			printf("This node contains probabilistic behaviours \n");
			solvingProbabilisticChoice(LTSnode, node, NULL, LTSnode->id,
					result);

		} else {
//			printf("This node doesn't contain probabilistic behaviours \n");
		}

	}

}

void solvingInternalChoice(stateLTS *LTSnode, Node *tree, char *appliedRule,
		char *LTSStateKey, processingOutput *result) {

//	Node *tree = LTSnode->node;
	if (tree) {
		int type = sT_getType(tree);

		if (appliedRule == NULL) {
			appliedRule = (char *) malloc(sizeof(char) * strlen("ND-Def"));
			if (type == IN_CHO) {
				appliedRule = "ND-Def";
			}
			if (type == EXT_CHO) {
				appliedRule = "ND-Ext";
			}
			if (type == PR_CHO) {
				appliedRule = "ND-Pro";
			}
			if (type == PARALLEL) {
				appliedRule = "ND-Par";
			}

		}

		if (sT_isOperator(type)) {
			if (type == IN_CHO) {
				Node *father = sT_getFatherNode(LTSnode->node, tree->key);

				//If the internal choice is located at the root node

				stateLTS *son1 = (stateLTS *) malloc(sizeof(stateLTS));
				stateLTS *son2 = (stateLTS *) malloc(sizeof(stateLTS));

				son1->numberOfTransitions = 0;
				son2->numberOfTransitions = 0;


				son1->node = (Node *) malloc(sizeof(Node));
				son2->node = (Node *) malloc(sizeof(Node));

				if (father == NULL) {
					sT_getSubTree(tree->left, son1->node, "0");
					sT_getSubTree(tree->right, son2->node, "0");

				} else {
					//It copies the whole binary tree structure
					sT_getSubTree(LTSnode->node, son1->node, "0");
					sT_getSubTree(LTSnode->node, son2->node, "0");

					Node *leftSon = (Node *) malloc(sizeof(Node));
					Node *rightSon = (Node *) malloc(sizeof(Node));

					char *fatherKey = (char *) malloc(
							sizeof(char) * strlen(father->key));
					strcpy(fatherKey, father->key);

					char *treeKey = (char *) malloc(
							sizeof(char) * strlen(tree->key));
					strcpy(treeKey, tree->key);

					leftSon = (Node *) tree->left;
					rightSon = (Node *) tree->right;

					char *leftKey = (char *) malloc(
							sizeof(char) * strlen(leftSon->key));
					strcpy(leftKey, leftSon->key);

					char *rightKey = (char *) malloc(
							sizeof(char) * strlen(rightSon->key));
					strcpy(rightKey, rightSon->key);

					sT_replacingNode(son1->node, fatherKey, treeKey, leftKey);
//					printf("Son1: ");sT_printout(son1->node);printf("\n");
					sT_replacingNode(son2->node, fatherKey, treeKey, rightKey);
//					printf("Son2: ");sT_printout(son2->node);printf("\n");
				}


				char *newKey1 = (char *) malloc(
						sizeof(char) * (strlen(LTSStateKey) + 2));
				char *newKey2 = (char *) malloc(
						sizeof(char) * (strlen(LTSStateKey) + 2));

				strcpy(newKey1, LTSStateKey);
				strcpy(newKey2, LTSStateKey);



				char tempNumber[2];
				sprintf(tempNumber,"%d",result->numOfStates);
				son1->id = strcat(newKey1, tempNumber);

				result->obtainedStates[result->numOfStates] = *son1;
				result->numOfStates++;

				tempNumber[0] = ' ';
				tempNumber[1] = ' ';
				sprintf(tempNumber,"%d",result->numOfStates);
				son2->id = strcat(newKey2, tempNumber);

				result->obtainedStates[result->numOfStates] = *son2;
				result->numOfStates++;

				transitionLTS *transition1 = (transitionLTS *) malloc(
						sizeof(transitionLTS));
				transitionLTS *transition2 = (transitionLTS *) malloc(
						sizeof(transitionLTS));

				int lengthAppliedRule = strlen(appliedRule);

				transition1->rule = (char *) malloc(
						sizeof(char) * lengthAppliedRule);
				transition2->rule = (char *) malloc(
						sizeof(char) * lengthAppliedRule);

				strcpy(transition1->rule, appliedRule);
				strcpy(transition2->rule, appliedRule);

				int lengthSubStateId = (strlen(LTSStateKey) + 1);

				transition1->subState = (char *) malloc(
						sizeof(char) * lengthSubStateId);
				transition2->subState = (char *) malloc(
						sizeof(char) * lengthSubStateId);

				strcpy(transition1->subState, newKey1);
				strcpy(transition2->subState, newKey2);

				LTSnode->subStates[LTSnode->numberOfTransitions] = *transition1;
				LTSnode->numberOfTransitions++;
				LTSnode->subStates[LTSnode->numberOfTransitions] = *transition2;
				LTSnode->numberOfTransitions++;
				return;

			} else {
				//If the internal choice is not located as a root node
				solvingInternalChoice(LTSnode, tree->left, appliedRule,
							LTSStateKey, result);
				solvingInternalChoice(LTSnode, tree->right, appliedRule,
							LTSStateKey, result);
			}
		}
	}
}

void solvingProbabilisticChoice(stateLTS *LTSnode, Node *tree,
		char *appliedRule, char *LTSStateKey, processingOutput *result) {

	int type = sT_getType(tree);
	if (sT_isOperator(type)) {
		if (type == PR_CHO) {

		}
	}

}

#endif /* OPERATIONALSEMANTICSCHOOSER_H_ */

